package org.chuan.base.service.impl;

import org.chuan.auth.domain.Permission;
import org.chuan.auth.mapper.PermissionMapper;
import org.chuan.base.annotation.SelfPermission;
import org.chuan.base.service.IAutoScanPermissionService;
import org.chuan.base.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Service
public class AutoScanPermissionServiceImpl implements IAutoScanPermissionService {

    /*
        1. 去扫描整个项目里的 Controller
        2. 通过反射获取 Controller的 Class对象
        3. 获取 class对象里面的方法
        4. 获取方法上面的注解 @SelfPermission(name = "...")
        5. 配置权限数据
            5.1 先获取类级别的权限 ==> 数据库里面体现一条数据【父级】
            5.2 再获取方法级别的权限 ==> 数据库里面体现一条数据和自己的 Controller父级关联
     */

    @Autowired
    private PermissionMapper permissionMapper;

    @Value("${scan.paths}")
    private String paths;
    @Value("${scan.tages}")
    private Boolean tages;

    @Override
    public void scan() {

        if (!tages) return;
        // 1. 获取项目里面需要扫描的 Controller ==>期望得到 List<Class>
        List<Class> allClassName = ClassUtils.getAllClassName(paths);
        ArrayList<Permission> permissions = new ArrayList<>();
        for (Class aClass : allClassName) {
            SelfPermission selfPermission = (SelfPermission) aClass.getAnnotation(SelfPermission.class);
            if (selfPermission == null) continue;
            Permission parent = new Permission();
            parent.setName(selfPermission.name());
            parent.setDescs(selfPermission.desc());
            RequestMapping requestMapping = (RequestMapping) aClass.getAnnotation(RequestMapping.class);
            parent.setUrl(requestMapping.value()[0]);
            parent.setSn(aClass.getSimpleName());
            permissions.add(parent);
            // 检查数据库是否已经有数据，有就修改，没有就新增
            Permission permission = permissionMapper.queryBySn(parent.getSn());
            if (permission != null) {
                parent.setId(permission.getId());
                permissionMapper.update(parent);
            }else {
                permissionMapper.save(parent);
            }
            // 解决子级资源菜单
            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                SelfPermission methodAnnotation = method.getAnnotation(SelfPermission.class);
                if (methodAnnotation == null) continue;
                Permission child = new Permission();
                child.setName(methodAnnotation.name());
                child.setDescs(methodAnnotation.desc());
                child.setSn(parent.getSn()+":"+method.getName());
                child.setParent_id(parent.getId());
                child.setUrl(parent.getUrl()+getChildUrl(method));
                Permission childInDb = permissionMapper.queryBySn(child.getSn());
                if (childInDb != null) {
                    child.setId(childInDb.getId());
                    permissionMapper.update(child);
                }else {
                    permissionMapper.save(child);
                }
            }
        }

    }

    private String getChildUrl(Method method){
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping != null) {
            return requestMapping.value().length>0?requestMapping.value()[0]:"";
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping != null) {
            return getMapping.value().length>0?getMapping.value()[0]:"";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            return postMapping.value().length>0?postMapping.value()[0]:"";
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            return putMapping.value().length>0?putMapping.value()[0]:"";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            return deleteMapping.value().length>0?deleteMapping.value()[0]:"";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            return patchMapping.value().length>0?patchMapping.value()[0]:"";
        }
        return "";
    }

}



